package searchkeyword

import (
	"context"
	"strings"
	"time"

	"mall/common/globalkey"
	"mall/common/modelx"
	"mall/common/utils/pointy"
	"mall/service/backend/model"
	"mall/service/backend/rpc/internal/svc"
	"mall/service/backend/rpc/internal/utils/errorhandler"
	"mall/service/backend/rpc/types/backend"

	"github.com/zeromicro/go-zero/core/logx"
)

type BackendGetSearchKeywordListLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

func NewBackendGetSearchKeywordListLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BackendGetSearchKeywordListLogic {
	return &BackendGetSearchKeywordListLogic{
		ctx:    ctx,
		svcCtx: svcCtx,
		Logger: logx.WithContext(ctx),
	}
}

func (l *BackendGetSearchKeywordListLogic) BackendGetSearchKeywordList(in *backend.SearchKeywordListReq) (*backend.SearchKeywordListResp, error) {
	// logrus.Info(fmt.Sprintf("SearchKeywordListReq: %+v", in))

	var orderBys []string
	if len(in.OrderBy) > 0 {
		for _, orderBy := range in.OrderBy {
			order := " ASC"
			if orderBy.Order == "1" {
				order = " DESC"
			}
			if orderBy.Field == "id" {
				orderBys = append(orderBys, model.SearchKeywordColumns.ID+order)
			}
			if orderBy.Field == "sort" {
				orderBys = append(orderBys, model.SearchKeywordColumns.Sort+order)
			}
			if orderBy.Field == "createdAt" {
				orderBys = append(orderBys, model.SearchKeywordColumns.CreatedAt+order)
			}
		}
	}

	var stati string
	var tab string
	if len(in.FilterBy) > 0 {
		for _, filterBy := range in.FilterBy {
			switch filterBy.Field {
			case "status":
				stati = filterBy.In
			case "type":
				tab = filterBy.In
			}
		}
	}

	var page uint64
	var pageSize uint64
	var restricted bool
	var withCount int
	var preCount int64
	filterMap := make(map[string]map[string][]any)
	resp := &backend.SearchKeywordListResp{}
	if in.Ids != nil && len(*in.Ids) > 0 {
		if vals := modelx.UniqueInterfaces(*in.Ids, 64); len(vals) == 0 {
			return resp, nil
		} else {
			filterMap[model.SearchKeywordColumns.ID] = map[string][]any{
				"in": vals,
			}
			restricted = true
			withCount = -1
			preCount = int64(len(vals))
		}
	}

	var statusIsSet bool
	var isAll bool
	statusMap := make(map[string][]any)
	switch tab {
	case "1": // 全部
		statusMap["notEqualTo"] = []any{globalkey.StatusDeleted}
		isAll = true
	case "2": // 正常
		filterMap[model.SearchKeywordColumns.Status] = map[string][]any{
			"equalTo": {globalkey.StatusEnabled},
		}
		statusIsSet = true
	case "3": // 禁用
		filterMap[model.SearchKeywordColumns.Status] = map[string][]any{
			"equalTo": {globalkey.StatusDisabled},
		}
		statusIsSet = true
	case "4": // 回收站
		filterMap[model.SearchKeywordColumns.Status] = map[string][]any{
			"equalTo": {globalkey.StatusDeleted},
		}
		statusIsSet = true
	}

	if !restricted {
		page = in.Page
		pageSize = in.PageSize
		withCount = 1
	}

	if in.Type != nil {
		filterMap[model.SearchKeywordColumns.Type] = map[string][]any{
			"equalTo": {*in.Type},
		}
	}
	if in.Title != nil && len(strings.TrimSpace(*in.Title)) >= 2 {
		filterMap[model.SearchKeywordColumns.Title] = map[string][]any{
			"contain": {strings.TrimSpace(*in.Title)},
		}
	}

	var startTimeIn []any
	var endTimeIn []any
	if in.StartTime != nil && len(strings.TrimSpace(*in.StartTime)) > 0 {
		if startTime, err := modelx.ParseLocalDate(strings.TrimSpace(*in.StartTime)); err == nil {
			startTimeIn = append(startTimeIn, startTime)
		}
	}
	if in.EndTime != nil && len(strings.TrimSpace(*in.EndTime)) > 0 {
		if endTime, err := modelx.ParseLocalDate(strings.TrimSpace(*in.EndTime)); err == nil {
			endTimeIn = append(endTimeIn, endTime)
		}
	}
	createdAtMap := make(map[string][]any)
	if len(startTimeIn) > 0 {
		createdAtMap["moreThanOrEqualTo"] = startTimeIn
	}
	if len(endTimeIn) > 0 {
		createdAtMap["lessThan"] = endTimeIn
	}
	filterMap[model.SearchKeywordColumns.CreatedAt] = createdAtMap

	if isAll {
		ret, _, err := l.svcCtx.SearchKeyword.GetList(l.ctx, model.M{
			"statistic": "1",
		}, 5, filterMap)
		if err != nil {
			// return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
			logx.Errorw("BackendGetSearchKeywordList GetList statistic err", logx.Field("detail", err.Error()))
		} else if len(ret) > 0 {
			statusStatisticMap := make(map[uint32]uint32)
			var total uint32
			for _, v := range ret {
				switch int32(v.Status) {
				case globalkey.StatusEnabled:
					statusStatisticMap[2] += uint32(v.Sort)
				case globalkey.StatusDisabled:
					statusStatisticMap[3] += uint32(v.Sort)
				case globalkey.StatusDeleted:
					statusStatisticMap[4] += uint32(v.Sort)
				}
				if v.Status != uint8(globalkey.StatusDeleted) {
					total += uint32(v.Sort)
				}
			}
			statusStatisticMap[1] = total
			resp.StatusStatisticMap = statusStatisticMap
		}
	}

	if !statusIsSet {
		statusIn := modelx.UniqueInterfaces(stati, 32)
		if len(statusIn) > 0 {
			statusMap["in"] = statusIn
		}
		if in.Status != nil {
			statusMap["equalTo"] = []any{*in.Status}
		}
		filterMap[model.SearchKeywordColumns.Status] = statusMap
	}

	var orderBy string
	if len(orderBys) > 0 {
		orderBy = strings.Join(orderBys, ",")
	} else {
		orderBy = model.SearchKeywordColumns.ID
	}
	res, count, err := l.svcCtx.SearchKeyword.GetList(l.ctx, model.M{
		"page":     page,
		"pageSize": pageSize,
		"orderBy":  orderBy,
	}, withCount, filterMap)
	if err != nil {
		return nil, errorhandler.DefaultRepositoryError(l.Logger, err, in)
	}

	if restricted {
		count = preCount
	}
	resp.Total = uint64(count)

	if len(res) > 0 {
		now := time.Now()
		for _, v := range res {
			var sort *uint32
			if v.Sort != uint16(globalkey.SystemDefaultSort) {
				sort = pointy.GetPointer(uint32(v.Sort))
			}
			var pending *uint32
			if v.StartedAt.Valid && v.StartedAt.Time.After(now) {
				pending = pointy.GetPointer(uint32(1))
			}
			var expired *uint32
			if v.EndedAt.Valid && v.EndedAt.Time.Before(now) {
				expired = pointy.GetPointer(uint32(1))
			}
			resp.List = append(resp.List, &backend.SearchKeywordInfo{
				Id:         &v.ID,
				Type:       pointy.GetPointer(uint32(v.Type)),
				Title:      &v.Title,
				LinkType:   pointy.GetPointer(uint32(v.LinkType)),
				LinkUrl:    &v.LinkURL,
				ObjectType: pointy.GetPointer(uint32(v.ObjectType)),
				ObjectId:   &v.ObjectID,
				Status:     pointy.GetPointer(uint32(v.Status)),
				Sort:       sort,
				CreatedAt:  pointy.GetPointer(modelx.FormatTime(v.CreatedAt, "")),
				UpdatedAt:  pointy.GetPointer(modelx.FormatTime(v.UpdatedAt, "")),
				DeletedAt:  pointy.GetPointer(modelx.FormatNullDotTime(v.DeletedAt, "")),
				StartedAt:  pointy.GetPointer(modelx.FormatNullDotTime(v.StartedAt, "")),
				EndedAt:    pointy.GetPointer(modelx.FormatNullDotTime(v.EndedAt, "")),
				Pending:    pending,
				Expired:    expired,
			})
		}
	}

	return resp, nil
}
